#include "SharedVariables.fxh"

float4x4 World;

texture lowTexture;
sampler lowTextureSampler = sampler_state
{
    Texture = (lowTexture);
    MAGFILTER = LINEAR;
    MINFILTER = LINEAR;
    MIPFILTER = LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};
texture lowNormal;
sampler lowNormalSampler = sampler_state
{
    Texture = (lowNormal);
    MAGFILTER = LINEAR;
    MINFILTER = LINEAR;
    MIPFILTER = LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};

texture midTexture;
sampler midTextureSampler = sampler_state
{
    Texture = (midTexture);
    MAGFILTER = LINEAR;
    MINFILTER = LINEAR;
    MIPFILTER = LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};
texture midNormal;
sampler midNormalSampler = sampler_state
{
    Texture = (midNormal);
    MAGFILTER = LINEAR;
    MINFILTER = LINEAR;
    MIPFILTER = LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};

texture highTexture;
sampler highTextureSampler = sampler_state
{
    Texture = (highTexture);
    MAGFILTER = LINEAR;
    MINFILTER = LINEAR;
    MIPFILTER = LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};
texture highNormal;
sampler highNormalSampler = sampler_state
{
    Texture = (highNormal);
    MAGFILTER = LINEAR;
    MINFILTER = LINEAR;
    MIPFILTER = LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};

texture slopeTexture;
sampler slopeTextureSampler = sampler_state
{
    Texture = (slopeTexture);
    MAGFILTER = LINEAR;
    MINFILTER = LINEAR;
    MIPFILTER = LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};
texture slopeNormal;
sampler slopeNormalSampler = sampler_state
{
    Texture = (slopeNormal);
    MAGFILTER = LINEAR;
    MINFILTER = LINEAR;
    MIPFILTER = LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};

struct VertexShaderInput
{
    float4 Position	: POSITION0;
    float3 Normal		: NORMAL;
    float2 TexCoord	: TEXCOORD0;
    float4 TexWeights	: TEXCOORD1;
    float3 Tangent		: TANGENT;
    float3 Binormal	: BINORMAL;
};

struct VertexShaderOutput
{
    float4 Position	: POSITION0;
    float2 TexCoord	: TEXCOORD0;
    float4 TexWeights	: TEXCOORD1;
    float2  Depth		: TEXCOORD2;
    float3x3 tangentToWorld	: TEXCOORD3;
};

struct PixelShaderOutput
{
	float4 Diffuse : COLOR0;
	float4 Depth : COLOR1;
	float4 Normal : COLOR2;
};

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
    VertexShaderOutput output;

    float4 pos = mul(input.Position, World);
    output.Position = mul(pos, ViewProj);
    output.Depth.x = output.Position.z;
	output.Depth.y = output.Position.w;
	output.TexCoord = input.TexCoord;
	output.TexWeights = input.TexWeights;
	
	output.tangentToWorld[0] = mul(input.Tangent, World);
	output.tangentToWorld[1] = mul(input.Binormal, World);
	output.tangentToWorld[2] = mul(input.Normal, World);

    return output;
}

float3 SampleTextures(float2 texCoords, float4 texWeights)
{
	float3 color = float3(0,0,0);
	if (texWeights.x > 0)
		color += tex2D(lowTextureSampler, texCoords) * texWeights.x;
	if (texWeights.y > 0)
		color += tex2D(midTextureSampler, texCoords) * texWeights.y;
	if (texWeights.z > 0)
		color += tex2D(highTextureSampler, texCoords) * texWeights.z;
    if (texWeights.w > 0)
		color += tex2D(slopeTextureSampler, texCoords) * texWeights.w;
    
    return color;
}

float3 SampleNormals(float2 texCoords, float4 texWeights)
{
	float3 color = float3(0,0,0);
	if (texWeights.x > 0)
		color += tex2D(lowNormalSampler, texCoords) * texWeights.x;
	if (texWeights.y > 0)
		color +=  tex2D(midNormalSampler, texCoords) * texWeights.y;
	if (texWeights.z > 0)
		color +=  tex2D(highNormalSampler, texCoords) * texWeights.z;
	if (texWeights.w > 0)
		color +=  tex2D(slopeNormalSampler, texCoords) * texWeights.w;
	
	return color;
}

PixelShaderOutput PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
    PixelShaderOutput output;
	float3 diffuseAttributes = SampleTextures(input.TexCoord, input.TexWeights);
	float3 normalAttributes = SampleNormals(input.TexCoord, input.TexWeights);
	
	output.Depth = input.Depth.x / input.Depth.y;
	output.Diffuse.rgb = diffuseAttributes;
	output.Diffuse.a = 0;
	float3 normalFromMap = normalAttributes;
	normalFromMap = 2.0f * normalFromMap - 1.0f;
	normalFromMap = normalize(mul(normalFromMap, input.tangentToWorld));
	output.Normal.rgb = 0.5f * (normalFromMap + 1.0f);
	output.Normal.a = 0.35f;
    return output;
}

technique Technique1
{
    pass Pass1
    {
        VertexShader = compile vs_2_0 VertexShaderFunction();
        PixelShader = compile ps_2_0 PixelShaderFunction();
    }
}
